#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <queue>
#include <string>

const int CAP = 5;

template <class T>
class BlockQueue{
	public:
	BlockQueue(int cap = CAP):_cap(cap), _csleep(0), _psleep(0){
		pthread_mutex_init(&_mutex, nullptr);
		pthread_cond_init(&_full_cond, nullptr);
		pthread_cond_init(&_empty_cond, nullptr);
	}

	void Equeue(T data){
		pthread_mutex_lock(&_mutex);
		
		//如果队列满了阻塞
		while(IsFull()){
			_psleep++;
			pthread_cond_wait(&_full_cond, &_mutex);
			_psleep--;
		}

		_queue.push(data);

		pthread_cond_signal(&_empty_cond);
		pthread_mutex_unlock(&_mutex);
	}

	T Pop(){
		pthread_mutex_lock(&_mutex);
		while(IsEmpty()){
			_csleep++;
			pthread_cond_wait(&_empty_cond, &_mutex);
			_csleep--;
		}

		T data = _queue.front();
		_queue.pop();

		pthread_cond_signal(&_full_cond);
		pthread_mutex_unlock(&_mutex);

		return data;
	}

	~BlockQueue(){
		pthread_mutex_destroy(&_mutex);
		pthread_cond_destroy(&_full_cond);
		pthread_cond_destroy(&_empty_cond);
	}

	private:
	std::queue<T> _queue;
	int _cap; //队列的容量
	pthread_mutex_t _mutex;
	pthread_cond_t _full_cond;
	pthread_cond_t _empty_cond;
	int _csleep; //休眠的消费者线程数
	int _psleep; //休眠的生产者线程数

	bool IsFull(){
		return _queue.size() == _cap;
	}

	bool IsEmpty(){
		return _queue.empty();
	}
};